﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Script.Serialization;

namespace SYMetro.Web.MVC.Filters
{
    public class JsonModelPostAttribute : ActionMethodSelectorAttribute
    {
        public enum ParameterType
        {
            Single,
            Multiple
        }

        private ParameterType _parameterType;
        public ParameterType MethodParameterType
        {
            get
            {
                return _parameterType;
            }
            set
            {
                _parameterType = value;
            }
        }

        public JsonModelPostAttribute()
        {
            _parameterType = ParameterType.Single;
        }

        public JsonModelPostAttribute(ParameterType type)
        {
            _parameterType = type;
        }

        public override bool IsValidForRequest(ControllerContext controllerContext, System.Reflection.MethodInfo methodInfo)
        {
            var c = GetDeserializedObject(controllerContext);            
            if (c == null)
            {
                return true;
            }
            if (MethodParameterType == ParameterType.Single)
            {
                return c is Dictionary<string, object>;
            }
            else
            {
                return c is object[];
            }
        }

        private static object GetDeserializedObject(ControllerContext controllerContext)
        {
            if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase))
            {
                // not JSON request
                return null;
            }

            controllerContext.HttpContext.Request.InputStream.Seek(0, SeekOrigin.Begin);

            StreamReader reader = new StreamReader(controllerContext.HttpContext.Request.InputStream);
            string bodyText = reader.ReadToEnd();

            controllerContext.HttpContext.Request.InputStream.Seek(0, SeekOrigin.Begin);

            if (String.IsNullOrEmpty(bodyText))
            {
                // no JSON data
                return null;
            }

            JavaScriptSerializer serializer = new JavaScriptSerializer();
            object jsonData = serializer.DeserializeObject(bodyText);
            return jsonData;
        }
    }
}